Simple Explicit Expressions with Subsystems
csdl
supports constructing model hierarchies via the Model.add
method.
This example shows one way to define and add a model to the model
hierarchy.
The example starts by creating an input 'x1'
to the main model (the
model at the top of the model hierarchy).
The variable 'x1'
is created in the current scope, so any parent
model cannot access 'x1'
unless 'x1'
is promoted to a higher
level in the hierarchy.
A new variable y4
in line 12 is defined in terms of x1
.
Note that y4
is the variable's name in Python, not CSDL.
The corresponding name for y4
in CSDL is defined as 'y4'
in line
45.
If a variable is not registered with a CSDL name, then CSDL
automatically names the variable.
The Python name for a variable does not need to match its name in CSDL,
but it is good practice to keep them consistent for readability.
In this example, 'subsystem'
declares the variable 'x1'
,
declaring an input to the model 'subsystem'
from either a parent
model, or a child model (in this case the parent model because
'subsystem'
has no children).
In the parent model, the create_input
method creates an input
'x1'
to the main model.
The variable 'x1'
belongs to the scope of
ExampleWithSubsystems
.
output in the parent Model
prior to the
call to Model.add
in order to update the input values in
'sys'
.
promotes on line 22
In this case, there is an input to the main model named 'x1'
in the
main model, so when 'subsystem'
is promoted, the declared variable
'x1'
can be referenced as 'x1'
instead of 'subsystem.x1'
after line 48.
Likewise, if the parent Model
is to use an output registered in
'subsystem'
, such as 'x2'
, then the user must call
Model.declare_variable
after Model.add
for that variable.
from csdl_om import Simulatorfrom csdl import Model, NonlinearBlockGSimport csdlimport numpy as np
class ExampleWithSubsystems(Model):
def define(self): # Create input to main model x1 = self.create_input('x1', val=40)
# Powers y4 = x1**2
# Create subsystem that depends on previously created # input to main model m = Model()
# This value is overwritten by connection from the main model a = m.declare_variable('x1', val=2) b = m.create_input('x2', val=12) m.register_output('prod', a * b) self.add(m, name='subsystem')
# declare inputs with default values # This value is overwritten by connection # from the submodel x2 = self.declare_variable('x2', val=3)
# Simple addition y1 = x2 + x1 self.register_output('y1', y1)
# Simple subtraction self.register_output('y2', x2 - x1)
# Simple multitplication self.register_output('y3', x1 * x2)
# Powers y5 = x2**2
# register outputs in reverse order to how they are defined self.register_output('y5', y5) self.register_output('y6', y1 + y5) self.register_output('y4', y4)
sim = Simulator(ExampleWithSubsystems())sim.run()
print('prod', sim['prod'].shape)print(sim['prod'])print('y1', sim['y1'].shape)print(sim['y1'])print('y2', sim['y2'].shape)print(sim['y2'])print('y3', sim['y3'].shape)print(sim['y3'])print('y4', sim['y4'].shape)print(sim['y4'])print('y5', sim['y5'].shape)print(sim['y5'])print('y6', sim['y6'].shape)print(sim['y6'])
[480.]y1 (1,)[52.]y2 (1,)[-28.]y3 (1,)[480.]y4 (1,)[1600.]y5 (1,)[144.]y6 (1,)[196.]